package frontdesk

import (
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"individual/controllers"
	"individual/models"
	"individual/utils"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
)

type UserController struct {
	controllers.BaseController
}

// 解析请求，并将请求体存储到v中
// unmarshalPayload
// @Param	v	interface{}	true	"接收解析后的请求体的变量"
func (u *UserController) unmarshalPayload(v interface{}) error {
	// json 解析
	// Unmarshal(data []byte, v interface{})
	// 将json字符串解码到相应的数据结构
	err := json.Unmarshal(u.Ctx.Input.RequestBody, &v)
	if err != nil {
		logs.Error("RequestBody 解析失败！")
		logs.Error("unmarshal payload of %s error: %s", u.Ctx.Request.URL.Path, err)
	}
	return nil
}

// Respond
// @Title Respond
// @Description 返回前端的信息
// @Param	code		 	int				true		"状态码"
// @Param	message		 	string			true		"返回信息"
// @Param	data		 	...interface{}	true		"数据"
func (u *UserController) Respond(code int, message string, data ...interface{}) {
	//c.Ctx.Output.SetStatus(code)
	var d interface{}
	if len(data) > 0 {
		d = data[0]
	}
	u.Data["json"] = struct {
		Code    int         `json:"code"`
		Message string      `json:"message"`
		Data    interface{} `json:"data,omitempty"`
	}{
		Code:    code,
		Message: message,
		Data:    d,
	}
	u.ServeJSON()
}

// RegisterAuth 注册oauth2信息
func RegisterAuth() {
	tokenUrl := "https://oauth.bannerstudio.club/user/oauthClientDetails"
	data := url.Values{
		"clientId":              []string{beego.AppConfig.String("CLIENT_ID")},
		"resourceIds":           []string{beego.AppConfig.String("RESOURCE_IDS")},
		"clientSecret":          []string{beego.AppConfig.String("CLIENT_SECRET")},
		"scope":                 []string{beego.AppConfig.String("SCOPE")},
		"authorizedGrantTypes":  []string{beego.AppConfig.String("AUTHORIZED_GRANT_TYPES")},
		"webServerRedirectUri":  []string{beego.AppConfig.String("REDIRECT_URI")},
		"authorities":           nil,
		"accessTokenValidity":   []string{beego.AppConfig.String("ACCESS_TOKEN_VALIDITY")},
		"refreshTokenValidity":  []string{beego.AppConfig.String("REFRESH_TOKEN_VALIDITY")},
		"additionallnformation": nil,
		"autoapprove":           nil,
	}
	_, err := http.PostForm(tokenUrl, data)
	if err != nil {
		log.Println(err)
		return
	}
}

// Login
// @Title Login
// @Description 跳转到授权中心
// @router /login [get]
func (u *UserController) Login() {
	toAuth := fmt.Sprintf("https://oauth.bannerstudio.club/oauth/authorize?"+
		"client_id=%s"+
		"&response_type=%s"+
		"&scope=all"+
		"&redirect_uri=%s",
		beego.AppConfig.String("CLIENT_ID"),
		beego.AppConfig.String("RESPONSE_TYPE"),
		beego.AppConfig.String("REDIRECT_URI"))
	u.Redirect(toAuth, http.StatusTemporaryRedirect)
}

// GetToken
// @Title GetToken
// @Description 从授权中心获取token
// @Success 200 {string}
// @Failure 403 body is empty
// @router /login/callback [get]
func (u *UserController) GetToken() {
	code := u.GetString("code")
	tokenUrl := "https://oauth.bannerstudio.club/oauth/token"
	data := url.Values{
		"code":          []string{code},
		"client_id":     []string{beego.AppConfig.String("CLIENT_ID")},
		"client_secret": []string{beego.AppConfig.String("CLIENT_SECRET")},
		"redirect_uri":  []string{beego.AppConfig.String("REDIRECT_URI")},
		"grant_type":    []string{beego.AppConfig.String("GRANT_TYPE")},
	}
	resp, err := http.PostForm(tokenUrl, data)
	if err != nil {
		log.Println(err)
		return
	}
	defer resp.Body.Close()
	bodyContent, err := ioutil.ReadAll(resp.Body)
	respMap := make(map[string]interface{})
	err = json.Unmarshal(bodyContent, &respMap)
	if err != nil {
		log.Println(err)
		u.Respond(http.StatusBadRequest, "获取失败")
		return
	}
	log.Println(respMap)
	u.Respond(http.StatusOK, "获取成功", respMap["access_token"].(string))
	return
}

// ParseToken
// @Title ParseToken
// @Description 解析token 获取authUser
// @Success 200 {string}
// @Failure 403 body is empty
// @router /getAuth [get]
func (u *UserController) ParseToken() {
	token := u.Ctx.Input.Header("token")
	tokenMap, err := utils.ValidateToken(token)
	if err != nil {
		logs.Error(err.Error())
		u.Data["json"] = models.GetRevaErr(err, "解析失败")
		return
	}
	log.Println(tokenMap)
	u.ServeJSON()
}

// GetUserinfo
// @Title	GetUserinfo
// @Description 获取用户信息
// @Success 201 获取用户信息成功
// @Failure 403 获取用户信息失败
// @router /getUserinfo/ [get]
func (c *UserController) GetUserinfo() {
	var user models.User
	err := c.O.QueryTable(new(models.User).TableName()).One(&user)
	if err != nil {
		c.Data["json"] = models.GetRevaErr(err, "获取用户信息失败")
		c.ServeJSON()
		return
	}
	user.Username = ""
	user.Password = ""
	user.AuthUsername = ""
	c.Data["json"] = models.GetRevaOk(user)
	c.ServeJSON()
}

// GetFriendLinks
// @Title	GetFriendLinks
// @Description 获取友链信息
// @Success 201 获取友链信息成功
// @Failure 403 获取友链信息失败
// @router /getFriendLinks/ [get]
func (c *UserController) GetFriendLinks() {
	var friendLinks []models.FriendLink
	_, err := c.O.QueryTable(new(models.FriendLink).TableName()).All(&friendLinks)
	if err != nil {
		c.Data["json"] = models.GetRevaErr(err, "获取友链信息失败")
		c.ServeJSON()
		return
	}
	c.Data["json"] = models.GetRevaOk(friendLinks)
	c.ServeJSON()
}

// GetDirectLinks
// @Title	GetDirectLinks
// @Description 获取自设链接
// @Success 201 获取自设链接成功
// @Failure 403 获取自设链接失败
// @router /getDirectLinks/ [get]
func (c *UserController) GetDirectLinks() {
	var friendLinks []models.DirectLink
	_, err := c.O.QueryTable(new(models.DirectLink).TableName()).All(&friendLinks)
	if err != nil {
		c.Data["json"] = models.GetRevaErr(err, "获取自设链接失败")
		c.ServeJSON()
		return
	}
	c.Data["json"] = models.GetRevaOk(friendLinks)
	c.ServeJSON()
}

// GetTags
// @Title	GetTags
// @Description 获取博主标签信息
// @Success 201 获取博主标签信息成功
// @Failure 403 获取博主标签信息失败
// @router /getTags/ [get]
func (c *UserController) GetTags() {
	var tags []models.Tag
	_, err := c.O.QueryTable(new(models.Tag).TableName()).All(&tags)
	if err != nil {
		c.Data["json"] = models.GetRevaErr(err, "获取博主标签信息失败")
		c.ServeJSON()
		return
	}
	c.Data["json"] = models.GetRevaOk(tags)
	c.ServeJSON()
}

// GetPartData
// @Title	GetPartData
// @Description 获取博客数目，分类数，标签数，总浏览量
// @Success 201 获取博客数目，分类数，标签数，总浏览量成功
// @Failure 403 获取博客数目，分类数，标签数，总浏览量失败
// @router /getPartData/ [get]
func (c *UserController) GetPartData() {
	blognum, err := c.O.QueryTable(new(models.Blog).TableName()).Filter("blog_state", 1).Count()
	if err != nil {
		c.Data["json"] = models.GetRevaErr(err, "获取博客数目失败")
		c.ServeJSON()
		return
	}
	typenum, err := c.O.QueryTable(new(models.Type).TableName()).Count()
	if err != nil {
		c.Data["json"] = models.GetRevaErr(err, "获取分类数目失败")
		c.ServeJSON()
		return
	}
	labelnum, err := c.O.QueryTable(new(models.Label).TableName()).Count()
	if err != nil {
		c.Data["json"] = models.GetRevaErr(err, "获取标签数目失败")
		c.ServeJSON()
		return
	}
	views, err := new(models.Blog).GetAllViews()
	if err != nil {
		c.Data["json"] = models.GetRevaErr(err, "获取总阅读量失败")
		c.ServeJSON()
		return
	}
	c.Data["json"] = models.GetRevaOk(map[string]interface{}{
		"blognum":  blognum,
		"typenum":  typenum,
		"labelnum": labelnum,
		"views":    views,
	})
	c.ServeJSON()
}
